package com.xunua.webrtcdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;

import com.xunua.webrtcdemo.databinding.ActivityMainBinding;
import com.xunua.webrtcdemo.utils.JsonUtil;
import com.xunua.webrtcdemo.utils.WebSecketBean;
import com.xunua.webrtcdemo.utils.WebSecketService;

import org.webrtc.AudioTrack;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RendererCommon;
import org.webrtc.RtpReceiver;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.VideoTrack;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding mBinding;
    private String TAG = "huang=====";

    private String wss_url = "wss://guardingeyeai.com/wss";
    private String turn_url = "turn:117.21.200.97:3478?transport=udp";
    private EglBase eglBase;
    private PeerConnectionFactory peerConnectionFactory;
    private List<PeerConnection.IceServer> iceServers;
    private PeerConnection peerConnection;
    private WebSecketBean webSecketBeanCandidate;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        mBinding = ActivityMainBinding.inflate(getLayoutInflater());
        super.onCreate(savedInstanceState);
        setContentView(mBinding.getRoot());
        initView();
    }

    private void initView() {
        connectionWebsocket();

        PeerConnectionFactory.InitializationOptions initializationOptions = PeerConnectionFactory.InitializationOptions.builder(this)
                .setEnableInternalTracer(true)
                .setFieldTrials("WebRTC-H264HighProfile/Enabled/")
                .createInitializationOptions();
        PeerConnectionFactory.initialize(initializationOptions);

        //创建EglBase对象
        eglBase = EglBase.create();


        // 将VideoTrack的frames渲染到SurfaceViewRenderer上
        mBinding.remoteRenderer.init(eglBase.getEglBaseContext(), null);
        mBinding.remoteRenderer.setMirror(false); // 如果你想要镜像显示，可以设置为true
        mBinding.remoteRenderer.setEnableHardwareScaler(true); // 开启硬件缩放
        mBinding.remoteRenderer.setFpsReduction(30.0f); // 设置帧率，可选
        mBinding.remoteRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL); // 设置缩放类型，可选
        mBinding.remoteRenderer.setZOrderMediaOverlay(true);
        mBinding.remoteRenderer.setZOrderOnTop(true);
        mBinding.remoteRenderer.setKeepScreenOn(true);


        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
        options.disableEncryption = true;
        options.disableNetworkMonitor = true;
        peerConnectionFactory = PeerConnectionFactory.builder()
                .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
                .setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
                .setOptions(options)
                .createPeerConnectionFactory();

        iceServers = new ArrayList<>();
        PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder(turn_url)
                .setUsername("admin")
                .setPassword("12345678")
                .createIceServer();
        iceServers.add(iceServer);

        PeerConnection.RTCConfiguration configuration = new PeerConnection.RTCConfiguration(iceServers);
        PeerConnection.Observer connectionObserver = getObserver();
        peerConnection = peerConnectionFactory.createPeerConnection(configuration, connectionObserver);

    }


    private void connectionWebsocket() {
        WebSecketService.getInstance().login("c3733cfbac9044319ec13ebad694fdc2", "11111111", new WebSecketService.OnWebSecketListern() {


            @Override
            public void onConnected() {

            }

            @Override
            public void onLoginStatus(int code, String viewer_id) {
                if (code == 200) {
                    createOffer();
                }else {

                }
            }

            @Override
            public void onReceiveOffer(WebSecketBean webSecketBean) {
                setRemoteDescription(webSecketBean,SessionDescription.Type.OFFER,"onReceiveOffer");
                createAnswer(webSecketBean);
            }

            @Override
            public void onReceiveAnswer(WebSecketBean webSecketBean) {
                //setRemoteDescription(webSecketBean,SessionDescription.Type.OFFER,"onReceiveAnswer");
            }

            @Override
            public void onReceiveCandidate(WebSecketBean webSecketBean) {
                webSecketBeanCandidate = webSecketBean;
                Log.e(TAG, "onReceiveCandidate======================start");
                boolean b = peerConnection.addIceCandidate(new IceCandidate(webSecketBean.id, webSecketBean.sdpMLineIndex, webSecketBean.candidate));
                Log.e(TAG, "onReceiveCandidate======================b:"+b);
                WebSecketService.getInstance().sendCandidate(webSecketBean);
            }
        });
    }


    private void createOffer() {
        Log.e(TAG, "createOffer==========createOffer====start");
        peerConnection.createOffer(new SdpObserver() {
            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                Log.e(TAG, "createOffer==========onSetSuccess====" + sessionDescription.description);
                Log.e(TAG, "createOffer==========onSetSuccess====" + sessionDescription.type);
                WebSecketService.getInstance().sendOffer(sessionDescription.description);
            }

            @Override
            public void onSetSuccess() {
                Log.e(TAG, "createOffer==========onSetSuccess====");

            }

            @Override
            public void onCreateFailure(String s) {
                Log.e(TAG, "createOffer==========onSetSuccess====");

            }

            @Override
            public void onSetFailure(String s) {
                Log.e(TAG, "createOffer==========onSetFailure====");

            }

        }, new MediaConstraints());
    }


    private void  createAnswer(WebSecketBean webSecketBean) {
        peerConnection.createAnswer(new SdpObserver() {
            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                Log.e(TAG, "createAnswer==============onCreateSuccess : " + sessionDescription.type);
                Log.e(TAG, "createAnswer==============onCreateSuccess : " + sessionDescription.description);
                webSecketBean.sdp = webSecketBean.sdp.replace("minptime=10;useinbandfec=1","minptime=10;useinbandfec=1;maxplaybackrate=8000;stereo=0");
                setLocalDescription(sessionDescription);
                WebSecketService.getInstance().sendAnswer(webSecketBean.sdp);
            }

            @Override
            public void onSetSuccess() {
                Log.e(TAG, "createAnswer==============onSetSuccess : ");

            }

            @Override
            public void onCreateFailure(String s) {
                Log.e(TAG, "createAnswer==============onCreateFailure : " + s);

            }

            @Override
            public void onSetFailure(String s) {
                Log.e(TAG, "createAnswer==============onSetFailure : " + s);

            }
        }, new MediaConstraints());
    }

    // 发送Offer到信令服务器的方法
    private void setLocalDescription(SessionDescription sessionDescription) {
        peerConnection.setLocalDescription(new SdpObserver() {
            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                Log.e(TAG, "setLocalDescription==============onCreateSuccess : " + sessionDescription.type);
                Log.e(TAG, "setLocalDescription==============onCreateSuccess : " + sessionDescription.description);
            }

            @Override
            public void onSetSuccess() {
                Log.e(TAG, "setLocalDescription==============onSetSuccess : ");
            }

            @Override
            public void onCreateFailure(String s) {
                Log.e(TAG, "setLocalDescription==============onCreateFailure : " + s);
            }

            @Override
            public void onSetFailure(String s) {
                Log.e(TAG, "setLocalDescription==============onSetFailure : " + s);

            }
        }, new SessionDescription(SessionDescription.Type.ANSWER,sessionDescription.description));

    }


    private void setRemoteDescription(WebSecketBean webSecketBean,SessionDescription.Type type ,String tag) {
        Log.e(TAG, "setRemoteDescription======from:"+tag+"====start====");
        peerConnection.setRemoteDescription(new SdpObserver() {
            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                Log.e(TAG, "setRemoteDescription======from:"+tag+"=====onCreateSuccess====" + sessionDescription.description);
                Log.e(TAG, "setRemoteDescription======from:"+tag+"======onCreateSuccess====" + sessionDescription.type);
            }

            @Override
            public void onSetSuccess() {
                Log.e(TAG, "setRemoteDescription======from:"+tag+"==========onSetSuccess : ");

            }

            @Override
            public void onCreateFailure(String s) {
                Log.e(TAG, "setRemoteDescription======from:"+tag+"==========onCreateFailure : " + s);

            }

            @Override
            public void onSetFailure(String s) {
                Log.e(TAG, "setRemoteDescription=======from:"+tag+"=========onSetFailure : " + s);
            }
        },new SessionDescription( type, webSecketBean.sdp));
    }


    public PeerConnection.Observer getObserver() {

        return new PeerConnection.Observer() {
            @Override
            public void onSignalingChange(PeerConnection.SignalingState signalingState) {
                Log.e(TAG, "PeerConnection==============onSignalingChange : " + signalingState.name());
                //have_remote_offer
                if (signalingState == PeerConnection.SignalingState.HAVE_REMOTE_OFFER) {
                }

            }

            @Override
            public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
                Log.e(TAG, "PeerConnection==============onIceConnectionChange : " + iceConnectionState.name());

            }

            @Override
            public void onIceConnectionReceivingChange(boolean b) {
                Log.e(TAG, "PeerConnection==============onIceConnectionReceivingChange : " + b);

            }

            @Override
            public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
                Log.e(TAG, "PeerConnection==============onIceGatheringChange : " + iceGatheringState.name());

            }

            @Override
            public void onIceCandidate(IceCandidate iceCandidate) {
                //onSendCandidate(that.observer, user_id, evt.candidate);
                Log.e(TAG, "PeerConnection==============onIceCandidate : " + iceCandidate.toString());
                WebSecketService.getInstance().sendCandidate(webSecketBeanCandidate);

            }

            @Override
            public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {
                Log.e(TAG, "PeerConnection==============onIceCandidatesRemoved : " + iceCandidates.toString());

            }

            @Override
            public void onAddStream(MediaStream mediaStream) {
                Log.e(TAG, "PeerConnection==============onAddStream : " + mediaStream.videoTracks.size());
                Log.e(TAG, "PeerConnection==============onAddStream : " + mediaStream.audioTracks.size());
                List<VideoTrack> videoTracks = mediaStream.videoTracks;
                if (videoTracks != null && videoTracks.size() >= 1) {
                    VideoTrack videoTrack = videoTracks.get(0);
                    if (videoTrack != null) {
                        videoTrack.addSink(mBinding.remoteRenderer);
                    }
                }
                List<AudioTrack> audioTracks = mediaStream.audioTracks;
                if (audioTracks != null && audioTracks.size() > 0) {
                    AudioTrack audioTrack = audioTracks.get(0);
                    if (audioTrack != null) {
                        audioTrack.setEnabled(true);
                        //声音调节
                        audioTrack.setVolume(10);
                    }
                }
            }

            @Override
            public void onRemoveStream(MediaStream mediaStream) {
                Log.e(TAG, "PeerConnection==============onRemoveStream : " + mediaStream.toString());

            }

            @Override
            public void onDataChannel(DataChannel dataChannel) {
                Log.e(TAG, "PeerConnection==============onDataChannel : " + dataChannel.toString());

            }

            @Override
            public void onRenegotiationNeeded() {
                Log.e(TAG, "PeerConnection==============onRenegotiationNeeded : ");

            }

            @Override
            public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
                Log.e(TAG, "PeerConnection==============onAddTrack : " + rtpReceiver.toString());
                Log.e(TAG, "PeerConnection==============mediaStreams : " + mediaStreams.toString());

            }
        };
    }


}